package com.danielstone.materialaboutlibrarydemo.snack;


import com.danielstone.materialaboutlibrarydemo.ResourceTable;
import com.danielstone.materialaboutlibrarydemo.snack.SnackBar.OnVisibilityChangeListener;
import ohos.aafwk.content.Intent;
import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorGroup;
import ohos.agp.animation.AnimatorProperty;
import ohos.agp.colors.RgbColor;
import ohos.agp.components.*;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.utils.Color;
import ohos.app.Context;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.utils.Sequenceable;

import java.util.LinkedList;
import java.util.Queue;

class SnackContainer extends StackLayout {

    private static final int ANIMATION_DURATION = 300;

    private static final String SAVED_MSGS = "SAVED_MSGS";

    private Queue<SnackHolder> mSnacks = new LinkedList<SnackHolder>();

    //    private AnimationSet mOutAnimationSet;
//    private AnimationSet mInAnimationSet;
    private AnimatorGroup mOutAnimationSet;
    private AnimatorGroup mInAnimationSet;
    private AnimatorProperty mSlideInAnimation;
    private AnimatorProperty mSlideOutAnimation;

    //使用eventHandler
    private EventHandler handler;

    public AnimatorGroup getmInAnimationSet() {
        return mInAnimationSet;
    }

    public SnackContainer(Context context) {
        super(context);
        init();
    }

    //    public SnackContainer(Context context, AttributeSet attrs) {
//        super(context, attrs);
//        init();
//    }
    public SnackContainer(Context context, AttrSet attrs) {
        super(context, attrs);
        init();
    }

    //    SnackContainer(ViewGroup container) {
//        super(container.getContext());
//
//        container.addView(this, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
//        setVisibility(View.GONE);
//        setId(R.id.snackContainer);
//        init();
//    }
    SnackContainer(ComponentContainer container) {
        super(container.getContext());

        container.addComponent(this, new ComponentContainer.LayoutConfig(ComponentContainer.LayoutConfig.MATCH_PARENT, ComponentContainer.LayoutConfig.MATCH_PARENT));
        setVisibility(Component.HIDE);
        setId(ResourceTable.Id_snackContainer);
        init();
    }

    private void init() {
//        mInAnimationSet = new AnimationSet(false);
        mInAnimationSet = new AnimatorGroup();

//        TranslateAnimation mSlideInAnimation = new TranslateAnimation(
//                TranslateAnimation.RELATIVE_TO_PARENT, 0.0f,
//                TranslateAnimation.RELATIVE_TO_PARENT, 0.0f,
//                TranslateAnimation.RELATIVE_TO_SELF, 1.0f,
//                TranslateAnimation.RELATIVE_TO_SELF, 0.0f);
        mSlideInAnimation = new AnimatorProperty();
        mSlideInAnimation.alpha(0.9f).moveFromX(0.0f).moveToX(0.0f).moveFromY(1.0f).moveToY(0.0f);
//        mSlideOutAnimation.setTarget(container);
//        mSlideInAnimation.moveFromX(0.0f);
//        mSlideInAnimation.moveToX(0.0f);
//        mSlideInAnimation.moveFromY(10.0f);
//        mSlideInAnimation.moveToY(0.0f);
//        mSlideInAnimation.alpha(1.0f);
//        AlphaAnimation mFadeInAnimation = new AlphaAnimation(0.0f, 1.0f);


//        mInAnimationSet.addAnimation(mSlideInAnimation);
//        mInAnimationSet.build().addAnimators(mSlideInAnimation);
//        mInAnimationSet.addAnimation(mFadeInAnimation);

//        mOutAnimationSet = new AnimationSet(false);
        mOutAnimationSet = new AnimatorGroup();

//        TranslateAnimation mSlideOutAnimation = new TranslateAnimation(
//                TranslateAnimation.RELATIVE_TO_PARENT, 0.0f,
//                TranslateAnimation.RELATIVE_TO_PARENT, 0.0f,
//                TranslateAnimation.RELATIVE_TO_SELF, 0.0f,
//                TranslateAnimation.RELATIVE_TO_SELF, 1.0f);
        mSlideOutAnimation = new AnimatorProperty();
        mSlideOutAnimation.alpha(0.1f).moveFromX(0.0f).moveToX(0.0f).moveFromY(0.0f).moveToY(1.0f);
//        mSlideOutAnimation.moveFromX(0.0f);
//        mSlideOutAnimation.moveToX(0.0f);
//        mSlideOutAnimation.moveFromY(0.0f);
//        mSlideOutAnimation.moveToY(10.0f);
//        mSlideOutAnimation.alpha(0.0f);

//        AlphaAnimation mFadeOutAnimation = new AlphaAnimation(1.0f, 0.0f);

//        mOutAnimationSet.addAnimation(mSlideOutAnimation);
//        mOutAnimationSet.build().addAnimators(mSlideOutAnimation);
//        mOutAnimationSet.addAnimation(mFadeOutAnimation);

//        mOutAnimationSet.setDuration(ANIMATION_DURATION);
//        mOutAnimationSet.setStateChangedListener(new Animator.StateChangedListener() {
        mSlideOutAnimation.setDuration(ANIMATION_DURATION);
        mSlideOutAnimation.setStateChangedListener(new Animator.StateChangedListener() {
            @Override
            public void onStart(Animator animator) {
                mOutAnimationSet.end();
            }

            @Override
            public void onStop(Animator animator) {

            }

            @Override
            public void onCancel(Animator animator) {

            }

            @Override
            public void onEnd(Animator animator) {
                removeAllComponents();

                if (!mSnacks.isEmpty()) {
                    sendOnHide(mSnacks.poll());
                }

                if (!isEmpty()) {
                    showSnack(mSnacks.peek());
                } else {
                    setVisibility(Component.HIDE);
                }
            }

            @Override
            public void onPause(Animator animator) {

            }

            @Override
            public void onResume(Animator animator) {

            }
        });
//        mOutAnimationSet.setAnimationListener(new Animation.AnimationListener() {
//            @Override
//            public void onAnimationStart(Animation animation) {
//
//            }
//
//            @Override
//            public void onAnimationEnd(Animation animation) {
//                removeAllViews();
//
//                if (!mSnacks.isEmpty()) {
//                    sendOnHide(mSnacks.poll());
//                }
//
//                if (!isEmpty()) {
//                    showSnack(mSnacks.peek());
//                } else {
//                    setVisibility(View.GONE);
//                }
//            }
//
////            @Override
////            public void onAnimationRepeat(Animation animation) {
////
////            }
//            @Override
//            public void onAnimationRepeat(Animator animation) {
//
//            }
//        });
    }

    //    @Override
    protected void onDetachedFromWindow(Component component) {
//        super.onDetachedFromWindow(component);
        BindStateChangedListener bindStateChangedListener = new BindStateChangedListener() {
            @Override
            public void onComponentBoundToWindow(Component component) {

            }

            @Override
            public void onComponentUnboundFromWindow(Component component) {

            }
        };
        bindStateChangedListener.onComponentUnboundFromWindow(component);
//        mInAnimationSet.cancel();
//        mOutAnimationSet.cancel();
        mSlideInAnimation.cancel();
        mSlideOutAnimation.cancel();
//        removeCallbacks(mHideRunnable);
        handler = new EventHandler(EventRunner.create());
        handler.removeTask(mHideRunnable);
        mSnacks.clear();
    }

    /*
     * Q Management *
     */

    public boolean isEmpty() {
        return mSnacks.isEmpty();
    }

    public Snack peek() {
        return mSnacks.peek().snack;
    }

    public Snack pollSnack() {
        return mSnacks.poll().snack;
    }

    public void clearSnacks(boolean animate) {
        mSnacks.clear();
//        removeCallbacks(mHideRunnable);
        handler = new EventHandler(EventRunner.create());
        handler.removeTask(mHideRunnable);
        if (animate) mHideRunnable.run();
    }

    /*
     * Showing Logic *
     */

    public boolean isShowing() {
        return !mSnacks.isEmpty();
    }

    public void hide() {
//        removeCallbacks(mHideRunnable);
        handler = new EventHandler(EventRunner.create());
        handler.removeTask(mHideRunnable);
        mHideRunnable.run();
    }

    //    public void showSnack(Snack snack, View snackView, OnVisibilityChangeListener listener) {
//        showSnack(snack, snackView, listener, false);
//    }
    public void showSnack(Snack snack, Component snackView, OnVisibilityChangeListener listener) {
        showSnack(snack, snackView, listener, false);
    }


    //    public void showSnack(Snack snack, View snackView, OnVisibilityChangeListener listener, boolean immediately) {
//        if (snackView.getParent() != null && snackView.getParent() != this) {
//            ((ViewGroup) snackView.getParent()).removeView(snackView);
//        }
//
//        SnackHolder holder = new SnackHolder(snack, snackView, listener);
//        mSnacks.offer(holder);
//        if (mSnacks.size() == 1) showSnack(holder, immediately);
//    }
    public void showSnack(Snack snack, Component snackView, OnVisibilityChangeListener listener, boolean immediately) {
        if (snackView.getComponentParent() != null && snackView.getComponentParent() != this) {
            snackView.getComponentParent().removeComponent(snackView);
        }

        SnackHolder holder = new SnackHolder(snack, snackView, listener);
        mSnacks.offer(holder);
        if (mSnacks.size() == 1) showSnack(holder, immediately);
    }

    private void showSnack(final SnackHolder holder) {
        showSnack(holder, false);
    }

    private void showSnack(final SnackHolder holder, boolean showImmediately) {

//        setVisibility(View.VISIBLE);
        setVisibility(Component.VISIBLE);

        sendOnShow(holder);

//        addView(holder.snackView);
        addComponent(holder.snackView);

        if(holder.snack.mIsBottom){
            DependentLayout.LayoutConfig config = new DependentLayout.LayoutConfig();
            config.width = DependentLayout.LayoutConfig.MATCH_PARENT;
            config.addRule(DependentLayout.LayoutConfig.ALIGN_PARENT_BOTTOM);
            setLayoutConfig(config);
        }

        holder.messageView.setText(holder.snack.mMessage);
        if (holder.snack.mActionMessage != null) {
//            holder.button.setVisibility(View.VISIBLE);
            holder.button.setVisibility(Component.VISIBLE);
            holder.button.setText(holder.snack.mActionMessage);
//            holder.button.setCompoundDrawablesWithIntrinsicBounds(holder.snack.mActionIcon, 0, 0, 0);
//            holder.button.setAroundElementsRelative(holder.snack.mActionIcon,0,0,0);
            // 这里需要设置边界
//            holder.button.getBubbleElement().setBounds(holder.snack.mActionIcon,0,0,0);
        } else {
//            holder.button.setVisibility(View.GONE);
            holder.button.setVisibility(Component.HIDE);
        }

//        holder.button.setTypeface(holder.snack.mTypeface);
//        holder.messageView.setTypeface(holder.snack.mTypeface);
        holder.button.setFont(holder.snack.mTypeface);
        holder.messageView.setFont(holder.snack.mTypeface);

        Color color1 = new Color(holder.snack.mBtnTextColor);
        holder.button.setTextColor(color1);
//        holder.snackView.setBackgroundColor(holder.snack.mBackgroundColor.getDefaultColor());
//        Color color = new Color(holder.snack.mBackgroundColor);
        RgbColor rgbColor = RgbColor.fromArgbInt(holder.snack.mBackgroundColor);
        ShapeElement element = new ShapeElement();
//        element.setRgbColor(new RgbColor(0,0,0));
        element.setRgbColor(rgbColor);
        holder.snackView.setBackground(element);
        if(holder.snack.mHeight > 0)
//            holder.snackView.getLayoutParams().height = this.getPxFromDp(holder.snack.mHeight);
            holder.snackView.getLayoutConfig().height = this.getPxFromDp(holder.snack.mHeight);

        if (showImmediately) {
//            mInAnimationSet.setDuration(0);
            mSlideInAnimation.setDuration(0);
        } else {
//            mInAnimationSet.setDuration(ANIMATION_DURATION);
            mSlideInAnimation.setDuration(ANIMATION_DURATION);
        }
//        startAnimation(mInAnimationSet);

//        mInAnimationSet.start();
        mSlideInAnimation.setTarget(holder.snackView);
//        mSlideInAnimation.setTarget(holder.button);
//        mSlideInAnimation.setTarget(holder.messageView);
        mSlideOutAnimation.setTarget(holder.snackView);
//        mSlideOutAnimation.setTarget(holder.button);
//        mSlideOutAnimation.setTarget(holder.messageView);
        mSlideInAnimation.start();
//        mSlideInAnimation.end();
//        mInAnimationSet.end();

        if (holder.snack.mDuration > 0) {
//            postDelayed(mHideRunnable, holder.snack.mDuration);
//            handler = new EventHandler(EventRunner.create());
            handler = new EventHandler(EventRunner.getMainEventRunner());
            handler.postTask(mHideRunnable, holder.snack.mDuration);
        }

//        mOutAnimationSet.start();

//        holder.snackView.setOnTouchListener(new View.OnTouchListener() {
//            @Override
//            public boolean onTouch(View v, MotionEvent event) {
//                float y = event.getY();
//
//                switch (event.getAction()) {
//                    case MotionEvent.ACTION_MOVE:
//                        int[] location = new int[2];
//                        holder.snackView.getLocationInWindow(location);
//                        if (y > mPreviousY) {
//                            float dy = y - mPreviousY;
//                            holder.snackView.offsetTopAndBottom(Math.round(4 * dy));
//
//                            if ((getResources().getDisplayMetrics().heightPixels - location[1]) - 100 <= 0) {
//                                removeCallbacks(mHideRunnable);
//                                sendOnHide(holder);
//                                startAnimation(mOutAnimationSet);
//
//                                if (!mSnacks.isEmpty()) {
//                                    mSnacks.clear();
//                                }
//                            }
//                        }
//                }
//
//                mPreviousY = y;
//
//                return true;
//            }
//        });
//        holder.snackView.setTouchEventListener(new TouchEventListener() {
//            @Override
//            public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
//                float y = touchEvent.getIndex();
//
//                switch (touchEvent.getAction()) {
//                    case TouchEvent.POINT_MOVE:
//                        int[] location = new int[2];
//                        location = holder.snackView.getLocationOnScreen();
//                        if (y > mPreviousY) {
//                            float dy = y - mPreviousY;
//                            int x = Math.round(4 * dy);
//                            holder.snackView.setTop(x);
//                            holder.snackView.setBottom(x);
////                            holder.snackView.offsetTopAndBottom(Math.round(4 * dy));
//
//                            int height = 2040; //本来应该从resource中获取
//                            if ((height - location[1]) - 100 <= 0) {
////                                removeCallbacks(mHideRunnable);
//                                handler = new EventHandler(EventRunner.create());
//                                handler.removeTask(mHideRunnable);
//                                sendOnHide(holder);
//                                mOutAnimationSet.start();
//
//                                if (!mSnacks.isEmpty()) {
//                                    mSnacks.clear();
//                                }
//                             }
//                        }
//                }
//                return false;
//            }
//        });
    }

    private void sendOnHide(SnackHolder snackHolder) {
        if (snackHolder.visListener != null) {
            snackHolder.visListener.onHide(mSnacks.size());
        }
    }

    private void sendOnShow(SnackHolder snackHolder) {
        if (snackHolder.visListener != null) {
            snackHolder.visListener.onShow(mSnacks.size());
        }
    }

    /*
     * Runnable stuff
     */

    private final Runnable mHideRunnable = new Runnable() {
        @Override
        public void run() {
//            if (View.VISIBLE == getVisibility()) {
//                startAnimation(mOutAnimationSet);
//            }
            if (Component.VISIBLE == getVisibility()) {
//                mOutAnimationSet.start();
//                mInAnimationSet.end();
//                mOutAnimationSet.end();
                mSlideOutAnimation.start();
//                mSlideOutAnimation.end();
            }
        }
    };

    /*
     * Restoration *
     */

    //    public void restoreState(Bundle state, View v) {
//        Parcelable[] messages = state.getParcelableArray(SAVED_MSGS);
//        boolean showImmediately = true;
//
//        for (Parcelable message : messages) {
//            showSnack((Snack) message, v, null, showImmediately);
//            showImmediately = false;
//        }
//    }
    public void restoreState(Intent state, Component v) {
        Sequenceable[] messages = state.getParcelableArrayParam(SAVED_MSGS);
        boolean showImmediately = true;

        for (Sequenceable message : messages) {
            showSnack((Snack) message, v, null, showImmediately);
            showImmediately = false;
        }
    }

    //    public Bundle saveState() {
//        Bundle outState = new Bundle();
//
//        final int count = mSnacks.size();
//        final Snack[] snacks = new Snack[count];
//        int i = 0;
//        for (SnackHolder holder : mSnacks) {
//            snacks[i++] = holder.snack;
//        }
//
//        outState.putParcelableArray(SAVED_MSGS, snacks);
//        return outState;
//    }
    public Intent saveState() {
        Intent outState = new Intent();

        final int count = mSnacks.size();
        final Snack[] snacks = new Snack[count];
        int i = 0;
        for (SnackHolder holder : mSnacks) {
            snacks[i++] = holder.snack;
        }

        outState.setParam(SAVED_MSGS, snacks);
        return outState;
    }

    private static class SnackHolder {
        //        final View snackView;
        final Component snackView;
        //        final TextView messageView;
        final Text messageView;
        //        final TextView button;
        final Text button;

        final Snack snack;
        final OnVisibilityChangeListener visListener;

        //        private SnackHolder(Snack snack, View snackView, OnVisibilityChangeListener listener) {
        private SnackHolder(Snack snack, Component snackView, OnVisibilityChangeListener listener) {
            this.snackView = snackView;
//            button = (TextView) snackView.findViewById(R.id.snackButton);
            button = (Text) snackView.findComponentById(ResourceTable.Id_snackButton);
//            messageView = (TextView) snackView.findViewById(R.id.snackMessage);
            messageView = (Text) snackView.findComponentById(ResourceTable.Id_snackMessage);

            this.snack = snack;
            visListener = listener;
        }
    }

    /*
     * Helpers
     */
    private int getPxFromDp(int dp) {
//        Resources rs = getResources();
//        int pxConverter = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, rs.getDisplayMetrics());
        int pxConverter = 2;
        int px = pxConverter * dp;
        return px;
    }

}
